package me.zhengjie.server.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.dao.*;
import me.zhengjie.dao.dto.ContainerQueryCriteria;
import me.zhengjie.enums.ConstantStatus;
import me.zhengjie.mapper.ContainerMapper;
import me.zhengjie.mapper.MesNestMapper;
import me.zhengjie.mapper.OutboundOrderHistoryMapper;
import me.zhengjie.server.ContainerService;
import me.zhengjie.utils.*;
import me.zhengjie.vo.OutBoundTaskToWcsVo;
import org.springframework.beans.factory.annotation.Autowired;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageResult;
import me.zhengjie.utils.PageUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;

@Service
public class ContainerServiceImpl extends ServiceImpl<ContainerMapper, ContainerDao> implements ContainerService {

    @Resource
    private ContainerMapper containerMapper;

    @Autowired
    private OutboundOrderHistoryMapper outboundOrderHistoryMapper;

    @Resource
    private MesNestMapper mesNestMapper;

    @Override
    public PageResult<ContainerDao> queryAll(ContainerQueryCriteria criteria, Page<Object> page) {
        return PageUtil.toPage(containerMapper.findAll(criteria, page));
    }

    @Override
    public List<ContainerDao> queryAll(ContainerQueryCriteria criteria) {
        return containerMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(ContainerDao resources) {
        resources.setCreateDate(new Timestamp(new Date().getTime()));
        containerMapper.insert(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ContainerDao resources) {
        ContainerDao container = getById(resources.getId());
        resources.setUpdateDate(new Timestamp(new Date().getTime()));
        container.copy(resources);
        containerMapper.updateById(container);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<String> ids) {
        containerMapper.deleteBatchIds(ids);
    }

    @Override
    public void download(List<ContainerDao> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ContainerDao container : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("载具类型", container.getType());
            map.put("载具位置", container.getLocal());
            map.put("冻结（0冻结/1启用）", container.getDisable());
            map.put("条码是否损坏（0可用/1损坏）", container.getBarCodeBad());
            map.put("载具是否损坏（0可用/1损坏）", container.getContainerBad());
            map.put("异常状态时间更新", container.getAbnormalDate());
            map.put("重量", container.getWeight());
            map.put("创建时间", container.getCreateDate());
            map.put("更新时间", container.getUpdateDate());
            map.put("长", container.getWLong());
            map.put("宽", container.getWWide());
            map.put("高", container.getWTall());
            map.put("是否有货（1有货/0无货）", container.getIsExist());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public void setQueryWrapper(LambdaQueryWrapper<ContainerDao> wrapper, ContainerDao containerDao) {
        if (containerDao.getId() != null) {
            wrapper.eq(ContainerDao::getId, containerDao.getId());
        }
        if (containerDao.getType() != null) {
            wrapper.eq(ContainerDao::getType, containerDao.getType());
        }
        if (containerDao.getLocal() != null) {
            wrapper.eq(ContainerDao::getLocal, containerDao.getLocal());
        }
        if (containerDao.getDisable() != null) {
            wrapper.eq(ContainerDao::getDisable, containerDao.getDisable());
        }
        if (containerDao.getIsExist() != null) {
            wrapper.eq(ContainerDao::getIsExist, containerDao.getIsExist());
        }
        if (containerDao.getBarCodeBad() != null) {
            wrapper.eq(ContainerDao::getBarCodeBad, containerDao.getBarCodeBad());
        }
        if (containerDao.getContainerBad() != null) {
            wrapper.eq(ContainerDao::getContainerBad, containerDao.getContainerBad());
        }
        if (containerDao.getAbnormalDate() != null) {
            wrapper.eq(ContainerDao::getAbnormalDate, containerDao.getAbnormalDate());
        }
        if (containerDao.getWeight() != null) {
            wrapper.eq(ContainerDao::getWeight, containerDao.getWeight());
        }
        if (containerDao.getCreateDate() != null) {
            wrapper.eq(ContainerDao::getCreateDate, containerDao.getCreateDate());
        }
        if (containerDao.getUpdateDate() != null) {
            wrapper.eq(ContainerDao::getUpdateDate, containerDao.getUpdateDate());
        }
        if (containerDao.getWLong() != null) {
            wrapper.eq(ContainerDao::getWLong, containerDao.getWLong());
        }
        if (containerDao.getWWide() != null) {
            wrapper.eq(ContainerDao::getWWide, containerDao.getWWide());
        }
        if (containerDao.getWTall() != null) {
            wrapper.eq(ContainerDao::getWTall, containerDao.getWTall());
        }
        if (containerDao.getIonLock() != null) {
            wrapper.eq(ContainerDao::getIonLock, containerDao.getIonLock());
        }
    }

    public void setUpdateWrapper(LambdaUpdateWrapper<ContainerDao> wrapper, ContainerDao containerDao) {
        wrapper.set(ContainerDao::getUpdateDate, new Date());
        if (containerDao.getType() != null) {
            wrapper.set(ContainerDao::getType, containerDao.getType());
        }
        if (containerDao.getLocal() != null) {
            wrapper.set(ContainerDao::getLocal, containerDao.getLocal());
        }
        if (containerDao.getDisable() != null) {
            wrapper.set(ContainerDao::getDisable, containerDao.getDisable());
        }
        if (containerDao.getBarCodeBad() != null) {
            wrapper.set(ContainerDao::getBarCodeBad, containerDao.getBarCodeBad());
        }
        if (containerDao.getContainerBad() != null) {
            wrapper.set(ContainerDao::getContainerBad, containerDao.getContainerBad());
        }
        if (containerDao.getAbnormalDate() != null) {
            wrapper.set(ContainerDao::getAbnormalDate, containerDao.getAbnormalDate());
        }
        if (containerDao.getWeight() != null) {
            wrapper.set(ContainerDao::getWeight, containerDao.getWeight());
        }
        if (containerDao.getItemBarCode() != null) {
            wrapper.set(ContainerDao::getItemBarCode, containerDao.getItemBarCode());
        }
        if (containerDao.getUpdateDate() == null) {
            wrapper.set(ContainerDao::getUpdateDate, new Date());
        }
        if (containerDao.getWLong() != null) {
            wrapper.set(ContainerDao::getWLong, containerDao.getWLong());
        }
        if (containerDao.getWWide() != null) {
            wrapper.set(ContainerDao::getWWide, containerDao.getWWide());
        }
        if (containerDao.getWTall() != null) {
            wrapper.set(ContainerDao::getWTall, containerDao.getWTall());
        }
        if (containerDao.getIonLock() != null) {
            wrapper.set(ContainerDao::getIonLock, containerDao.getIonLock());
        }
        if (containerDao.getIsExist() != null) {
            wrapper.set(ContainerDao::getIsExist, containerDao.getIsExist());
            if (containerDao.getIsExist().equals(ConstantStatus.Out_OF_Stock)) {
                wrapper.set(ContainerDao::getItemBarCode, null);
                wrapper.set(ContainerDao::getWeight, 0.0);
            }
        }

    }

    @Override
    public List<ContainerDao> findDataList(ContainerDao containerDao) {
        LambdaQueryWrapper<ContainerDao> wrapper = new LambdaQueryWrapper<>(containerDao);
        setQueryWrapper(wrapper, containerDao);
        return this.list(wrapper);
    }

    @Override
    public ContainerDao findDataOne(String containerCode) {
        LambdaQueryWrapper<ContainerDao> wrapper = new LambdaQueryWrapper<>();
        ContainerDao containerDao = new ContainerDao().setId(containerCode);
        setQueryWrapper(wrapper, containerDao);
        return this.getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDataById(ContainerDao containerDao) {
        if (containerDao.getId() == null || containerDao.getId().isEmpty()) {
            return false;
        }
        LambdaUpdateWrapper<ContainerDao> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ContainerDao::getId, containerDao.getId());
        this.setUpdateWrapper(wrapper, containerDao);
        return this.update(null, wrapper);
    }

    @Override
    public HandOutBandReturnDao handOutBandDetail(HandOutBandDao dao) {
        HandOutBandReturnDao result = new HandOutBandReturnDao();
        ContainerDao dao1 = containerMapper.selectOne(new LambdaQueryWrapper<ContainerDao>()
                .eq(ContainerDao::getId, dao.getCode()));
        result.setLocal(dao1.getLocal());
        result.setType(dao1.getType());
        result.setCode(dao1.getId());
        result.setContainerStatus(dao1.getDisable());
        result.setHeight(dao1.getWTall());
        result.setWeight(dao1.getWeight());
        List<MesNest> mesNest = mesNestMapper.selectList(new LambdaQueryWrapper<MesNest>().eq(MesNest::getContainerCode, dao.getCode()));
        if (mesNest.size() > 0) {
            result.setMesNest(mesNest);
        }
        return result;
    }

    @Override
    public Object handScan(HandSacnDao param) {
        String store = containerMapper.selectRecordByContainer(param.getStore());
        if (store != null) {
            return "整板出库：分拣区";
        }
        return "整板出库：增加物料入库";
    }

    @Override
    public Object handOut(HandSacnDao param) {
        int i = containerMapper.updateStore(param.getStore());
        return i > 0 ? true : false;
    }

    @Override
    public PageResult<ContainerDao> findNewContainer(ContainerParamDao containerDao) {
        List<ContainerDao> result = baseMapper.selectListOfPage(containerDao);
        List<ContainerDao> paging = PageUtil.paging(containerDao.getPage() - 1, containerDao.getSize(), result);
        for (ContainerDao dao : paging) {
            List<MesNest> mesNest = mesNestMapper.selectList(new LambdaQueryWrapper<MesNest>().eq(MesNest::getContainerCode, dao.getId()));
            dao.setDetail(mesNest);
        }
       return PageUtil.toPage( result);
    }

    @Override
    public Object handOutBand(HandToOutBandDao param) throws IOException {
        //判断权限
        String currentUsername = "System";
        try {
            currentUsername = SecurityUtils.getCurrentUsername();
        } catch (Exception e) {
        }
        if (!currentUsername.equals("System")) {
            throw new RuntimeException("没有权限！");
        }
        if (param.getType() == 0) {
// 均衡出库
            String floor = "M2";
            String locationG1 = containerMapper.selectPositionForBalan(floor);
            int i = containerMapper.updateLocal(locationG1);
            if (locationG1 == null) {
                throw new IOException("当前有其他任务正在出库中, 请等待！");
            }
            for (HandToOutBandDetailDao detailDao : param.getDetailDaos()) {
                OutBoundTaskToWcsVo request = new OutBoundTaskToWcsVo();
                request.setWmsTaskId(UUID.randomUUID().toString());
                request.setContainerCode(detailDao.getContainerCode());
                request.setSource(containerMapper.selectPositionByContainer(detailDao.getContainerCode()));
                request.setDestination(locationG1);
                sendToWcs(request);
            }
            /*
             * 1.判断是否有该容器
             * 2 判断有无工位
             * 3 根据人员信息决定出楼层的货物
             */

        } else if (param.getType() == 1) {
//抽检出库
            for (HandToOutBandDetailDao detailDao : param.getDetailDaos()) {
                String locationG2 = containerMapper.selectPositionForSort();
                if (locationG2 == null) {
                    throw new IOException("抽检区暂时没有位置, 请等待！");
                }
                TaskRecordDao dao = new TaskRecordDao();
                dao.setContainerCode(detailDao.getContainerCode());
                dao.setEndLocation(locationG2);
                dao.setStartLocation(containerMapper.selectPositionByContainer(detailDao.getContainerCode()));
                dao.setWeight(detailDao.getWeight());
                dao.setDocuments(param.getCode());
                dao.setMaterialCode(detailDao.getMaterialCode());
                //生成一个insert插入语句
                OutboundOrderHistory history = new OutboundOrderHistory();
                history.setOutboundOrderNo(param.getCode());
                history.setStatus(1);
                outboundOrderHistoryMapper.insert(history);
//                int insertDao = containerMapper.insertToTaskCode(dao);
                int i = containerMapper.updateLocalForSort(locationG2);
                OutBoundTaskToWcsVo request = new OutBoundTaskToWcsVo();
                request.setWmsTaskId(UUID.randomUUID().toString());
                request.setContainerCode(detailDao.getContainerCode());
                request.setSource(containerMapper.selectPositionByContainer(detailDao.getContainerCode()));
                request.setDestination(locationG2);
                sendToWcs(request);
            }
            /*
             * 1.判断是否有该容器
             * 2 送至抽检区
             */
        } else if (param.getType() == 2) {
            String location = containerMapper.selectPosition();
            int i = containerMapper.updateLocal(location);
            if (location == null) {
                throw new IOException("当前有其他任务正在出库中, 请等待！");
            }
            for (HandToOutBandDetailDao detailDao : param.getDetailDaos()) {
                OutBoundTaskToWcsVo request = new OutBoundTaskToWcsVo();
                request.setWmsTaskId(UUID.randomUUID().toString());
                request.setContainerCode(detailDao.getContainerCode());
                request.setSource(containerMapper.selectPositionByContainer(detailDao.getContainerCode()));
                request.setDestination(location);
                sendToWcs(request);
            }
//增加物料出库
            /*
             * 1.判断是否有该容器
             * 2 反向工位
             * 3 判断工位有无位置
             */
        } else {

        }

        return true;
    }

    public void sendToWcs(OutBoundTaskToWcsVo outBoundTaskToWcsVo) throws IOException {
        String url = "http://localhost:8005//delivery/task";
        // 发送POST请求
        String response = HttpUtil.sendPost(url, outBoundTaskToWcsVo);
        try {
            JSONObject jsonResponse = JSONUtil.parseObj(response);
            String code = jsonResponse.getStr("code");
            if ("200".equals(code)) {
                System.out.println("将信息成功发送至WCS系统，响应正常");
            } else {
                String message = jsonResponse.getStr("message", "未知错误");
                System.err.println("发送失败，错误码: " + code + ", 错误信息: " + message);
            }
        } catch (Exception e) {
            System.err.println("解析响应JSON失败: ");
        }
    }

}
